using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace SmartWallpaperChanger
{
    public class WallpaperSetter
    {
        readonly ImageResizer resizer;
        string wallpaperPath;

        #region Properties
        /// <summary>
        /// Gets or sets the path where the wallpaper gets saved.
        /// </summary>
        public string WallpaperPath
        {
            get { return wallpaperPath; }
            set { wallpaperPath = value; }
        }

        /// <summary>
        /// Gets the current monitor size.
        /// </summary>
        private Size MonitorSize
        {
            get { return System.Windows.Forms.SystemInformation.PrimaryMonitorSize; }
        }
        #endregion

        #region Imported Methods
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
        public const int SPI_SETDESKWALLPAPER = 20;
        public const int SPIF_SENDCHANGE = 0x2;
        #endregion

        public WallpaperSetter()
        {
            resizer = new ImageResizer();
            WallpaperPath = Path.Combine(Directory.GetCurrentDirectory(), "wallpaper.bmp");
        }

        public WallpaperSetter(string wallpaperPath)
        {
            resizer = new ImageResizer();
            WallpaperPath = wallpaperPath;
        }

        /// <summary>
        /// Sets given wallpaper as background image.
        /// </summary>
        public void SetWallpaper(string fileName)
        {
            try
            {
                SetFillMode();
                CreateBitmap(fileName);
                
                int nResult = SystemParametersInfo(SPI_SETDESKWALLPAPER, 1, WallpaperPath, SPIF_SENDCHANGE);
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Could not set wallpaper. See inner Exeption(s) for details.", ex);
            }
        }

        #region Helper methods
        /// <summary>
        /// Sets the fillmode.
        /// </summary>
        private void SetFillMode()
        {
            try
            {
                RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
                key.SetValue(@"WallpaperStyle", "0");
                key.SetValue(@"TileWallpaper", "0");
                key.Close();
            }
            catch(Exception ex)
            {
                throw new InvalidOperationException("Could not be set fillmode.", ex);
            }
        }

        /// <summary>
        /// Creates a bitmap to set as wallpaper.
        /// </summary>
        /// <param name="fileName">File which should be converted to a wallpaper bitmap.</param>
        private void CreateBitmap(string fileName)
        {
            if (wallpaperPath == fileName) return;

            try
            {
                Bitmap image = new Bitmap(fileName);
                bool needsResize = image.Height != MonitorSize.Height || image.Width != MonitorSize.Width;

                if (needsResize)
                {
                    resizer.TargetSize = MonitorSize;
                    image = resizer.Resize(image);
                }
                
                image.Save(WallpaperPath, System.Drawing.Imaging.ImageFormat.Bmp);
                image.Dispose();
                GC.Collect();
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Could not create Image.", ex);
            }
        }
        #endregion
    }
}